package com.allinpay;

import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author : wushikai
 * <p>
 * date : 2020-11-14
 */
public class Person {


    public Integer height = 180;
    public Integer weight = 22;
    private Integer age = 18;
    public String gender = "male";

    public ArrayList<String> name;

    public int no;

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Person() {
    }

    public Person(Integer height, Integer weight, Integer age, String gender) {
        this.height = height;
        this.weight = weight;
        this.age = age;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "height=" + height +
                ", weight=" + weight +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    private void privateTest() {
        System.out.println("Person.privateTest()");
    }


}

class Test {

    public static ArrayList<String> getFieldsDescription(Field[] fields) {
        ArrayList<String> fieldList = new ArrayList<>();

        for (Field f : fields) {
            int mod = f.getModifiers() & Modifier.fieldModifiers();
            String modifiers = Modifier.toString(mod);

            Class<?> type = f.getType();
            String typeName = type.getSimpleName();

            String fieldName = f.getName();

            fieldList.add(modifiers + "  " + typeName + "  " + fieldName);
        }

        return fieldList;
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        Person person = new Person();
        Class<? extends Person> personClazz = person.getClass();
        System.out.println(personClazz.getName());
        Field[] declaredFields = personClazz.getDeclaredFields();
        for (Field field : declaredFields) {
            int modifiers = field.getModifiers();
            int mod = field.getModifiers() & Modifier.fieldModifiers();
            String modifierStr = Modifier.toString(mod);
            Type genericType = field.getGenericType();
            String typeName = genericType.getTypeName();
            if (typeName!=null){
                System.out.println(typeName);
            }
            Type type = field.getType();
            String typeSimpleName = ((Class) type).getSimpleName();
            System.out.println();
            System.out.println(modifierStr + "  " + typeSimpleName + "  " + field.getName() +";");

            System.out.println(   field.getName() +" 是基本类型字节码吗??  " +  field.getType().getClass().isPrimitive()); //?????????


        }

        System.out.println(int.class.isPrimitive());
        System.out.println(float.class.isPrimitive());
        System.out.println(double.class.isPrimitive());
        System.out.println(char.class.isPrimitive());
        System.out.println(boolean.class.isPrimitive());
        System.out.println(byte.class.isPrimitive());
        System.out.println(short.class.isPrimitive());
        System.out.println(long.class.isPrimitive());



        System.out.println(" ///-------------------------------------");

        Method[] methods = personClazz.getDeclaredMethods();
        for (Method method : methods) {

            int modifiers = method.getModifiers();
            int mod = method.getModifiers() & Modifier.fieldModifiers();
            String modifierStr = Modifier.toString(mod);
            String methodName = method.getName();
            Class<?>[] parameterTypes = method.getParameterTypes();
            int i = 0;
            String paras = "";
            for (Class clazz : parameterTypes) {
                String paraTypename = clazz.getSimpleName();

                String var = "var" + (i++);
                paras =  paras + paraTypename + " " + var + ", ";

            }

            Class<?> returnType = method.getReturnType();
            String returnTypeStr = returnType.getName();



            if (paras.length() > 2) {
                paras = paras.substring(0, paras.length() - 2);
            }

            System.out.println(modifierStr +"  "  +returnTypeStr + "  "   + methodName + "( " + paras + ") ");

        }
        System.out.println("-----------------------------------------");
        Constructor<?>[] constructors = personClazz.getDeclaredConstructors();
        for (Constructor constructor : constructors){

            String constructorName = constructor.getName();
            Class[] parameterTypes = constructor.getParameterTypes();

            int mod = constructor.getModifiers() & Modifier.fieldModifiers();
            String modifierStr = Modifier.toString(mod);

            int i = 0;
            String paras = "";
            for (Class clazz : parameterTypes) {
                String paraTypename = clazz.getSimpleName();

                String var = "var" + (i++);
                paras =  paras+ paraTypename + " " + var + ", ";

            }
            if (paras.length() > 2) {
                paras = paras.substring(0, paras.length() - 2);
            }

            System.out.println(modifierStr  + "  "   + constructorName + "( " + paras + ") ");
        }



        Field field = personClazz.getDeclaredField("age");
        field.setAccessible(true);
        Object filedObj = field.get(person);
        System.out.println(filedObj.toString());

        //使用 mybatis 源码中的 defaultObjectFactory 创建对象的方式1
        DefaultObjectFactory defaultObjectFactory = new DefaultObjectFactory();
        Person person1 = defaultObjectFactory.create(Person.class);
        System.out.println(person1.toString());


        List<Class<?>> classList = new ArrayList<>();
        classList.add(Integer.class);
        classList.add(Integer.class);
        classList.add(Integer.class);
        classList.add(String.class);


        List<Object> list = new ArrayList<>();
        list.add(181);
        list.add(22);
        list.add(19);
        list.add("female");

        //使用 mybatis 源码中的 defaultObjectFactory 创建对象的方式2
        //  Person person2 = defaultObjectFactory.create(Person.class, classList, list);
        //  System.out.println(person2.toString());


        Class[] classes = new Class[classList.size()];
        classes = classList.toArray(classes);
        /*  for (int i = 0; i < classes.length; i++) {
            System.out.println(classes[i].toString());
        }

        for (int i = 0; i < classes1.length; i++) {
            System.out.println(classes1[i].toString());
        }*/
        // Constructor  constructor =Person.class.getDeclaredConstructor(classes);
        Constructor constructor = Person.class.getDeclaredConstructor(classList.toArray(new Class[classList.size()])); //必须转成一个数组;
        // Constructor  constructor =   Person.class.getDeclaredConstructor(classList);
        System.out.println(constructor.getName());
        Object o = constructor.newInstance(0, 0, 0, "nothing");
        System.out.println(o.toString());

    }
}